package com.bantianyao.common.other

import com.google.gson.Gson
import com.google.gson.TypeAdapter
import com.google.gson.TypeAdapterFactory
import com.google.gson.internal.`$Gson$Types`
import com.google.gson.reflect.TypeToken
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonToken
import com.google.gson.stream.JsonWriter
import java.lang.reflect.Type

/**
 * @Author: Jasper Jiao
 * @Date: 2022/1/6 10:53
 * @Description: 将Json中null value自定义解析成预设值，（需要完善非原始类型的实现）
 */
class GsonDefaultAdapterFactory : TypeAdapterFactory {
    override fun <T : Any> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
        if (type.type == String::class.java) {
            return createStringAdapter()
        }
        if (type.type == Int::class.java) {
            return createIntAdapter()
        }
        if (type.type == Long::class.java) {
            return createLongAdapter()
        }
        if (type.type == Double::class.java) {
            return createDoubleAdapter()
        }
        if (type.type == Float::class.java) {
            return createDoubleAdapter()
        }
        if (type.type == Boolean::class.java) {
            return createBooleanAdapter()
        }
        if (type.rawType == List::class.java || type.rawType == Collection::class.java) {
            return createCollectionAdapter(type, gson)
        }

        if (type.type != Any::class.java) {
        }
        return null
    }

    /**
     * null 替换成空 0（Int）
     */
    private fun <T : Any> createIntAdapter(): TypeAdapter<T> {
        return object : TypeAdapter<Int>() {
            override fun write(writer: JsonWriter, value: Int?) {
                if (value == null) {
                    writer.value(0)
                } else {
                    writer.value(value)
                }
            }

            override fun read(reader: JsonReader): Int {
                // null替换为""
                if (reader.peek() == JsonToken.NULL) {
                    reader.nextNull()
                    return 0
                }
                return reader.nextInt()
            }
        } as TypeAdapter<T>
    }

    /**
     * null 替换成空 0（Long）
     */
    private fun <T : Any> createLongAdapter(): TypeAdapter<T> {
        return object : TypeAdapter<Long>() {
            override fun write(writer: JsonWriter, value: Long?) {
                if (value == null) {
                    writer.value(0)
                } else {
                    writer.value(value)
                }
            }

            override fun read(reader: JsonReader): Long {
                // null替换为""
                if (reader.peek() == JsonToken.NULL) {
                    reader.nextNull()
                    return 0
                }
                return reader.nextLong()
            }
        } as TypeAdapter<T>
    }

    /**
     * null 替换成空 0.0（Double）
     */
    private fun <T : Any> createDoubleAdapter(): TypeAdapter<T> {
        return object : TypeAdapter<Double>() {
            override fun write(writer: JsonWriter, value: Double?) {
                if (value == null) {
                    writer.value(0.0)
                } else {
                    writer.value(value)
                }
            }

            override fun read(reader: JsonReader): Double {
                // null替换为""
                if (reader.peek() == JsonToken.NULL) {
                    reader.nextNull()
                    return 0.0
                }
                return reader.nextDouble()
            }
        } as TypeAdapter<T>
    }

    /**
     * null 替换成空 false
     */
    private fun <T : Any> createBooleanAdapter(): TypeAdapter<T> {
        return object : TypeAdapter<Boolean>() {
            override fun write(writer: JsonWriter, value: Boolean?) {
                if (value == null) {
                    writer.value(false)
                } else {
                    writer.value(value)
                }
            }

            override fun read(reader: JsonReader): Boolean {
                // null替换为""
                if (reader.peek() == JsonToken.NULL) {
                    reader.nextNull()
                    return false
                }
                return reader.nextBoolean()
            }
        } as TypeAdapter<T>
    }

    /**
     * null替换成空List
     */
    private fun <T : Any> createCollectionAdapter(
        type: TypeToken<T>,
        gson: Gson
    ): TypeAdapter<T>? {
        val rawType = type.rawType
        if (!Collection::class.java.isAssignableFrom(rawType)) {
            return null
        }
        val elementType: Type = `$Gson$Types`.getCollectionElementType(type.type, rawType)
        val elementTypeAdapter: TypeAdapter<Any> =
            gson.getAdapter(TypeToken.get(elementType)) as TypeAdapter<Any>

        return object : TypeAdapter<Collection<Any>>() {
            override fun write(writer: JsonWriter, value: Collection<Any>?) {
                writer.beginArray()
                value?.forEach {
                    elementTypeAdapter.write(writer, it)
                }
                writer.endArray()
            }

            override fun read(reader: JsonReader): Collection<Any> {
                // null替换为空list
                if (reader.peek() == JsonToken.NULL) {
                    reader.nextNull()
                    return listOf()
                }
                val list = mutableListOf<Any>()
                reader.beginArray()
                while (reader.hasNext()) {
                    val element = elementTypeAdapter.read(reader)
                    list.add(element)
                }
                reader.endArray()
                return list
            }
        } as TypeAdapter<T>
    }

    /**
     * null 替换成空字符串
     */
    private fun <T : Any> createStringAdapter(): TypeAdapter<T> {
        return object : TypeAdapter<String>() {
            override fun write(writer: JsonWriter, value: String?) {
                if (value == null) {
                    writer.value("")
                } else {
                    writer.value(value)
                }
            }

            override fun read(reader: JsonReader): String {
                // null替换为""
                if (reader.peek() == JsonToken.NULL) {
                    reader.nextNull()
                    return ""
                }
                return reader.nextString()
            }
        } as TypeAdapter<T>
    }
}